﻿namespace Blaze.Framework
{
    using System;
    using Pooling;
    using UnityEngine;
    using UnityEngine.Assertions;
    using Object = UnityEngine.Object;

    /// <summary>
    /// 为<see cref="GameObject"/>提供常用的扩展功能。
    /// </summary>
    public static class GameObjectExtension
    {
        /// <summary>
        /// 获取或增加一个指定的组件。
        /// </summary>
        /// <typeparam name="T">组件类型</typeparam>
        /// <returns>组件</returns>
        public static T GetOrAddComponent<T>(this GameObject obj) where T : Component
        {
            var component = obj.GetComponent<T>();
            if (component == null)
                component = obj.AddComponent<T>();
            return component;
        }

        /// <summary>
        /// 获取或增加一个指定的组件。
        /// </summary>
        /// <typeparam name="T">组件类型</typeparam>
        /// <returns>组件</returns>
        public static Component GetOrAddComponent(this GameObject obj, Type type)
        {
            var component = obj.GetComponent(type);
            if (component == null)
                component = obj.AddComponent(type);
            return component;
        }

        /// <summary>
        /// 移除指定类型的组件。
        /// </summary>
        /// <typeparam name="T">组件类型</typeparam>
        /// <returns>组件是否存在</returns>
        public static bool RemoveComponent<T>(this GameObject obj) where T : Component
        {
            var component = obj.GetComponent<T>();
            if (component == null)
                return false;
            Object.Destroy(component);
            return true;
        }

        #region Pooling

        /// <summary>
        /// 从池中获取指定已实例化的预设的对象，若不存在则会创建新的。
        /// </summary>
        /// <param name="prefab">预设</param>
        public static GameObject GetFromPool(Object prefab)
        {
            Assert.IsNotNull(prefab);
            var poolId = prefab.GetInstanceID();
            var pool = GameObjectPoolManager.Instance.GetPool(poolId);
            if (pool == null)
                pool = GameObjectPoolManager.Instance.Create(poolId, prefab, 1);
            var ret = pool.Get();
            return ret;
        }

        /// <summary>
        /// 将对象返回到对象池。
        /// </summary>
        /// <param name="obj">对象池</param>
        public static void ReturnToPool(GameObject obj)
        {
            if (BlazeEngine.IsShuttingDown)
                return;
            Assert.IsNotNull(obj);
            GameObjectPoolManager.Instance.Put(obj);
        }

        /// <summary>
        /// 为指定的预设创建对象池。
        /// </summary>
        /// <param name="prefab">预设</param>
        /// <param name="initialSize">池的初始大小</param>
        /// <returns>对象池的编号</returns>
        public static int CreatePool(Object prefab, int initialSize)
        {
            Assert.IsNotNull(prefab);
            var pool = GameObjectPoolManager.Instance.Create(prefab.GetInstanceID(), prefab, initialSize);
            return pool.Id;
        }

        /// <summary>
        /// 删除指定预设所对应的对象池。
        /// </summary>
        /// <param name="prefab">预设</param>
        public static void DeletePool(Object prefab)
        {
            Assert.IsNotNull(prefab);
            var poolId = prefab.GetInstanceID();
            GameObjectPoolManager.Instance.DeletePool(poolId);
        }

        #endregion
    }
}